///**
//Copyright (c) 2007-2013 Alysson Bessani, Eduardo Alchieri, Paulo Sousa, and the authors indicated in the @author tags
//
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
//*/
//package bftsmart.demo.random;
//
//import bftsmart.consensus.app.BatchAppResultImpl;
//import bftsmart.tom.MessageContext;
//import bftsmart.tom.ReplyContextMessage;
//import bftsmart.tom.ServiceReplica;
//import bftsmart.tom.server.defaultservices.DefaultRecoverable;
//
//import java.io.*;
//import java.math.BigInteger;
//import java.util.List;
//
///**
// *
// * @author Joao Sousa
// */
//public final class RandomServer extends DefaultRecoverable {
//
//    private int value = 0;
//    private int iterations = 0;
//    private int id = -1;
//
//    private ServiceReplica replica;
//
//    public ServiceReplica getReplica() {
//		return replica;
//	}
//
//	public void setReplica(ServiceReplica replica) {
//		this.replica = replica;
//	}
//
//
//    public RandomServer(int id) {
//    	replica = new ServiceReplica(id, this, this);
//        this.id = id;
//    }
//
//    public byte[] execute(byte[] command, MessageContext msgCtx) {
//        iterations++;
//        try {
//            DataInputStream input = new DataInputStream(new ByteArrayInputStream(command));
//            int operator = input.readInt();
//            int argument = (new BigInteger(msgCtx.getNonces())).intValue() + 1;
//
//            System.out.println("(" + id + ")[server] Argument: " + argument);
//            switch (operator) {
//                case 0:
//                    value = value + argument;
//                    System.out.println("(" + id + ")[server] Operator: +");
//                    break;
//                case 1:
//                    value = value - argument;
//                    System.out.println("(" + id + ")[server] Operator: -");
//                    break;
//                case 2:
//                    value = value * argument;
//                    System.out.println("(" + id + ")[server] Operator: *");
//                    break;
//                case 3:
//                    value = value / argument;
//                    System.out.println("(" + id + ")[server] Operator: /");
//                    break;
//            }
//
//            if (msgCtx == null) {
//
//                System.out.println("Message Context is still null!!!???");
//                System.exit(0);
//            }
//
//            System.out.println("(" + id + ")[server] (" + iterations + " / " +
//                    msgCtx.getConsensusId() + " / " + msgCtx.getRegency() + " / "
//                    + msgCtx.getLeader() +  ") Current value: " + value);
//
//            ByteArrayOutputStream out = new ByteArrayOutputStream(4);
//            new DataOutputStream(out).writeInt(value);
//            return out.toByteArray();
//        } catch (IOException ex) {
//            System.err.println("Invalid request received!");
//            return new byte[0];
//        }
//    }
//
//    /**
//     * Just return the current value
//     *
//     * @param command Command to b executed
//     * @param msgCtx Context of  the message received
//     * @return Reply t obe sent to the client
//     */
//    @Override
//    public byte[] appExecuteUnordered(byte[] command, MessageContext msgCtx) {
//        iterations++;
//        try {
//            System.out.println("(" + id + ")[server] (" + iterations + " / " +
//                    msgCtx.getConsensusId() + ") Current value: " + value);
//
//            ByteArrayOutputStream out = new ByteArrayOutputStream(4);
//            new DataOutputStream(out).writeInt(value);
//            return out.toByteArray();
//        } catch (IOException ex) {
//            System.err.println("Never happens!");
//            return new byte[0];
//        }
//    }
//
//        public static void main(String[] args){
//        if(args.length < 1) {
//            System.out.println("Use: java RandomServer <processId>");
//            System.exit(-1);
//        }
//
//        new RandomServer(Integer.parseInt(args[0]));
//
//    }
//
//    public byte[] getState() {
//
//        byte[] b = new byte[4];
//        //byte[] b = new byte[1024 * 1024 * 30];
//        //for (int i = 0; i > b.length; i++) b[i] = (byte) i;
//        for (int i = 0; i < 4; i++) {
//            int offset = (b.length - 1 - i) * 8;
//            b[i] = (byte) ((value >>> offset) & 0xFF);
//        }
//        return b;
//
//        //throw new UnsupportedOperationException("Not supported yet.");
//    }
//
//    public void setState(byte[] state) {
//
//        int value = 0;
//        for (int i = 0; i < 4; i++) {
//            int shift = (4 - 1 - i) * 8;
//            value += (state[i] & 0x000000FF) << shift;
//        }
//
//        this.value = value;
//    }
//
//    @Override
//    public void installSnapshot(byte[] state) {
//        int value = 0;
//        for (int i = 0; i < 4; i++) {
//            int shift = (4 - 1 - i) * 8;
//            value += (state[i] & 0x000000FF) << shift;
//        }
//
//        this.value = value;
//    }
//
//    @Override
//    public byte[] getSnapshot() {
//        byte[] b = new byte[4];
//        //byte[] b = new byte[1024 * 1024 * 30];
//        //for (int i = 0; i > b.length; i++) b[i] = (byte) i;
//        for (int i = 0; i < 4; i++) {
//            int offset = (b.length - 1 - i) * 8;
//            b[i] = (byte) ((value >>> offset) & 0xFF);
//        }
//        return b;
//    }
//
//    @Override
//    public byte[][] appExecuteBatch(byte[][] commands, MessageContext[] msgCtxs, boolean fromConsensus) {
//        byte [][] replies = new byte[commands.length][];
//        for (int i = 0; i < commands.length; i++) {
//            //replies[i] = execute(commands[i], (msgCtxs  != null ? msgCtxs[i] : null));
//            replies[i] = execute(commands[i], msgCtxs[i]);
//        }
//        return replies;
//    }
//
//    @Override
//    public byte[][] appExecuteBatch(byte[][] commands, MessageContext[] msgCtxs, boolean fromConsensus, List<ReplyContextMessage> replyContextMessages) {
//        return appExecuteBatch(commands, msgCtxs, fromConsensus);
//    }
//
//    @Override
//    public BatchAppResultImpl preComputeAppHash(byte[][] commands) {
//        return null;
//    }
//
//    @Override
//    public List<byte[]> updateAppResponses(List<byte[]> asyncResponseLinkedList, byte[] commonHash, boolean isConsistent) {
//        return null;
//    }
//
//    @Override
//    public void preComputeAppCommit(String batchId) {
//
//    }
//
//    @Override
//    public void preComputeAppRollback(String batchId) {
//
//    }
//
//}
